<?php

	namespace org\tekuna\framework\info;

	use org\tekuna\base\Tekuna;

	use org\tekuna\core\application\Application;
	use org\tekuna\core\configuration\XmlConfiguration;
	use org\tekuna\core\context\Context;
	use org\tekuna\core\event\Event;
	use org\tekuna\core\event\AbstractEventListener;
	use org\tekuna\core\event\TriggeredEvent;
	use org\tekuna\core\event\HandledListener;
	use org\tekuna\core\event\ApplicationRunEvent;
	use org\tekuna\core\util\WeightedList;

	use org\tekuna\framework\action\HttpActionEvent;
	use org\tekuna\framework\interceptor\InterceptorsListLoadedEvent;
	use org\tekuna\framework\response\BeforeResponseSendEvent;
	use org\tekuna\framework\response\Response;
	use org\tekuna\framework\response\http\ContentResponse;
	use org\tekuna\framework\response\cli\CliResponse;
	
	
	/**
	 * This is a special listener that can be used in application development.
	 * It triggers an InformationEvent that some internal objects listen to. By
	 * using this listener, in-depht knowledge about various object states can 
	 * be acquired and displayed, such as:
	 * 
	 *   - the matched action
	 *   - the interceptor chain
	 *   - loaded plugins
	 *   - response information
	 *   - request information
	 *   - application context
	 *   - configuration files
	 *   - the configuration
	 *   - event listeners
	 *   - class loaders
	 */
	class ApplicationInfoListener extends AbstractEventListener {

		/**
		 * @return boolean returns true for BeforeResponseSendEvents
		 */
		public function handlesEvent(Event $objEvent) {

			// TODO: require activation via GET or environment variable?
			return $objEvent instanceof BeforeResponseSendEvent;
		}
		
		
		/**
		 * Registers some internal objects as listeners, triggers 
		 * the InformationEvent and displays (or logs) the information.
		 */
		public function handleEvent(Event $objEvent) {

			// register default framework information listener
			$objFIPL = new FrameworkInformationProviderListener();
			$objFIPL -> setApplicationContext($this -> getApplicationContext());
			$this -> getApplicationContext() -> getEventManager() -> registerListener($objFIPL, 100);
			
			// register plugin manager
			$objPM = $this -> getApplicationContext() -> getPluginManager();
			$this -> getApplicationContext() -> getEventManager() -> registerListener($objPM);
			
			// send information request event
			$objInformationEvent = new InformationEvent();
			$this -> getApplicationContext() -> getEventManager() -> triggerEvent($objInformationEvent);
			
			// get the response event
			$objResponse = $objEvent -> getResponse();
			
			// deliver information according to response types
			if ($objResponse instanceof ContentResponse) {
				
				// add to HTTP response
				$objResponse -> appendContent($this -> buildHtmlInformation($objInformationEvent));
			}
			elseif ($objResponse instanceof CliResponse) {
				
				// echo to console
				echo $this -> buildTextInformation($objInformationEvent);
			}
			else {
				
				// fallback: log into logfile
				$objLogger = Tekuna :: getLogger(__CLASS__);
				$objLogger -> info($this -> buildTextInformation($objInformationEvent));
			}
		}
		
		
		private function buildHtmlInformation(InformationEvent $objInformationEvent) {
			
			$sInformation = '';
			$sTOC = '';
			
			foreach ($objInformationEvent -> getInfoSections() as $sTitle => $sContent) {
				
				$sAnchor = 'tekuna-information-'. preg_replace('~[^a-z0-9\.\-_]~', '_', strtolower($sTitle));
				
				$sTOC .= "<li><a href=\"#$sAnchor\">$sTitle</a></li>";
				
				$sContent = htmlspecialchars($sContent);
				
				$sInformation .= "<a name=\"$sAnchor\"></a>";
				$sInformation .= "<h2>$sTitle</h2>";
				$sInformation .= "<pre>$sContent</pre>";
			}

			$sOutput = '<div id="tekuna-application-information"><hr />';
			$sOutput .= '<h1>Application Information</h1>';
			$sOutput .= '<ol>';
			$sOutput .= $sTOC;
			$sOutput .= '</ol>';
			$sOutput .= $sInformation;
			$sOutput .= '</div>';
			
			return $sOutput;
		}
		
		
		private function buildTextInformation(InformationEvent $objInformationEvent) {
			
			$sOutput = "\n\n\n";
			$sOutput .= "###########################\n";
			$sOutput .= "# Application Information #\n";
			$sOutput .= "###########################\n\n\n";
						
			foreach ($objInformationEvent -> getInfoSections() as $sTitle => $sContent) {
				
				$sOutput .= $sTitle ."\n";
				$sOutput .= str_repeat('-', strlen($sTitle)) ."\n\n";
				$sOutput .= $sContent ."\n\n";
			}
			
			return $sOutput;
		}
	}